package com.zlyx.easy.database.supports;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import com.zlyx.easy.core.buffer.EasyBuffer;
import com.zlyx.easy.core.map.EasyMap;
import com.zlyx.easy.core.map.Maps;
import com.zlyx.easy.core.reflect.FieldMap;
import com.zlyx.easy.core.reflect.FieldUtils;
import com.zlyx.easy.core.utils.DateUtils;
import com.zlyx.easy.core.utils.ObjectUtils;
import com.zlyx.easy.core.utils.StringUtils;
import com.zlyx.easy.database.annotations.EasySelect;
import com.zlyx.easy.database.enums.SqlType;
import com.zlyx.easy.database.utils.TableUtils;

/**
 * @Auth 赵光
 * @Describle
 * @2019年1月13日 下午4:20:38
 */
public class SqlFactory {

	protected Class<?> tableCls;

	protected String tableName;

	/**
	 * 存放构成Sql语句的不同部分
	 */
	protected EasyMap<String, String> sqlElements = Maps.newMap();

	/**
	 * 存放Sql条件片段
	 */
	protected EasyMap<String, String> fragments = Maps.newMap();

	public SqlFactory(Class<?> tableCls) {
		this.tableCls = tableCls;
		this.tableName = TableUtils.getTableName(tableCls);
		this.sqlElements.addValue(SqlSupport.TYPENAME, SqlType.Select.toString());
		this.sqlElements.addValue(SqlSupport.TABLENAME, tableName);
	}

	/**
	 * 设置结果集
	 * 
	 * @param fields
	 * @return
	 * @throws Exception
	 */
	public boolean results(String[] fields) throws Exception {
		EasyBuffer results = EasyBuffer.newBuffer();
		if ((fields.length == 1 && EasySelect.FILED_ALL.equals(fields[0])) || fields.length == 0) {
			List<Field> fieldList = FieldUtils.getAllFields(tableCls);
			boolean isStatic = false;
			for (Field field : fieldList) {
				isStatic = Modifier.isStatic(field.getModifiers());
				if (!isStatic && field.getType().toString().contains("java")) {
					appendColumn(results, field.getName());
				}
			}
		} else {
			for (String fieldName : fields) {
				appendColumn(results, fieldName);
			}
		}
		sqlElements.put(SqlSupport.RESULTS, results.clearEnd());
		return true;
	}

	/**
	 * 拼接结果集
	 * 
	 * @param results
	 * @param fieldName
	 * @throws NoSuchFieldException
	 */
	private void appendColumn(EasyBuffer results, String fieldName) throws NoSuchFieldException {
		String columnName;
		columnName = fieldName;
		if (!columnName.contains("_")) {
			columnName = TableUtils.getColumnName(tableCls.getDeclaredField(columnName));
		}
		if (fieldName.equals(columnName)) {
			results.append(columnName);
		} else {
			results.append(columnName).append(" as ").append(fieldName);
		}
		results.append(", ");
	}

	/**
	 * where条件开始
	 * 
	 * @param paramsMap
	 * @param strings
	 * 
	 * @return
	 */
	public void where(String[] conditions, EasyMap<String, Object> paramsMap) {
		EasyBuffer eb = new EasyBuffer(SqlSupport.WHERE);
		Set<String> keys = new HashSet<>();
		for (String condition : conditions) {
			for (Entry<String, Object> entry : paramsMap.entrySet()) {
				if (ObjectUtils.isNotEmpty(entry.getValue())) {
					if (condition.contains("#{" + entry.getKey() + "}")) {
						condition = condition.replace("#{" + entry.getKey() + "}", String.valueOf(entry.getValue()));
						keys.add(entry.getKey());
					} else if (condition.contains("${" + entry.getKey() + "}")) {
						condition = condition.replace("${" + entry.getKey() + "}", String.valueOf(entry.getValue()));
						keys.add(entry.getKey());
					} else if (condition.contains("{" + entry.getKey() + "}")) {
						condition = condition.replace("{" + entry.getKey() + "}", String.valueOf(entry.getValue()));
						keys.add(entry.getKey());
					}
				}
			}
			if (!StringUtils.isEmpty(condition) && !condition.contains("{")) {
				eb.append(condition).append(" and ");
			}
		}
		FieldMap mapClass = FieldUtils.getFieldMap(tableCls);
		for (Entry<String, Object> entry : paramsMap.entrySet()) {
			if (ObjectUtils.isNotEmpty(entry.getValue()) && mapClass.contains(entry.getKey())
					&& !keys.contains(entry.getKey())) {
				eb.append(entry.getKey() + " = " + getValue(entry.getValue())).append(" and ");
			}
		}
		if (eb.toString().endsWith(SqlSupport.WHERE)) {
			sqlElements.put(SqlSupport.CONDITON, eb.replace(SqlSupport.WHERE, "").toString());
		} else {
			sqlElements.put(SqlSupport.CONDITON, eb.clearEnd(4));
		}
	}

	public String getValue(Object value) {
		if (Integer.class == value.getClass()) {
			return String.valueOf(value);
		} else if (Date.class == value.getClass()) {
			value = DateUtils.format(value);
		}
		return String.valueOf("'" + value + "'");
	}

	/**
	 * 标记一个sql语句结束并返回成型的sql语句
	 * 
	 * @return
	 */
	public String assemble(Object target) {
		return SqlAssembler.assemble(target, sqlElements);
	}

	@Override
	public String toString() {
		return assemble(this);
	}
}
